/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2006-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.test;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import junit.framework.Assert;
import junit.framework.AssertionFailedError;
/**
* <p>ThrowableAnticipator class.</p>
*
* @author ranger
* @version $Id: $
*/
public class ThrowableAnticipator extends Assert {
/** Constant <code>IGNORE_MESSAGE="*** ThrowableAnticipator ignore Throwab"{trunked}</code> */
public final static String IGNORE_MESSAGE =
"*** ThrowableAnticipator ignore Throwable.getMessage() ***";
private List<Throwable> m_anticipated;
private List<Throwable> m_unanticipated;
private boolean m_failFast;
/**
* Create a new anticipator with default failFast setting of true.
*/
public ThrowableAnticipator() {
this(true);
}
/**
* Create a new anticipator with the specified failFast setting.
*
* @param failFast whether unanticipated exceptions will cause an immediate
* junit.framework.Assert#fail(String). See #setFailFast(boolean)
* for details.
*/
public ThrowableAnticipator(boolean failFast) {
init();
m_failFast = failFast;
}
private void init() {
m_anticipated = new ArrayList<Throwable>();
m_unanticipated = new ArrayList<Throwable>();
m_failFast = true;
}
/**
* Anticipate a specific java.lang.Throwable.
*
* @param t The java.lang.Throwable to anticipate. Both the class and the
* message will be matched.
*/
public void anticipate(Throwable t) {
m_anticipated.add(t);
}
/**
* Process a received throwable. See #setFailFast(boolean) for the effects
* of the failFast setting on when errors are signaled.
*
* @param t The received throwable.
* @throws AssertionFailedError if failFast is set to true and an
* unanticipated java.lang.Throwable is received.
*/
public void throwableReceived(Throwable t) {
if (t == null) {
throw new IllegalArgumentException("Throwable must not be null");
}
boolean foundMatch = false;
for (Throwable our : m_anticipated) {
if (t.getClass().isAssignableFrom(our.getClass())) {
if (IGNORE_MESSAGE.equals(our.getMessage())
|| (t.getMessage() == null && our.getMessage() == null)
|| (t.getMessage() != null
&& t.getMessage().equals(our.getMessage()))) {
m_anticipated.remove(our);
foundMatch = true;
break;
}
}
}
if (!foundMatch) {
throwableFailedMatch(t);
}
}
private void throwableFailedMatch(Throwable t) {
if (m_failFast) {
fail("Received an unexpected Exception: " + t.toString(), t);
} else {
m_unanticipated.add(t);
}
}
/**
* Set the failFast value for this anticipator. This controls what happens
* when an unanticipation throwable is received #receiveThrowable(Throwable).
*
* @param failFast when set to true (the default), an unanticipated throwable
* will cause #receiveThrowable(Throwable) to call
* junit.framework.Assert#fail(). When set to false, the error will
* be delayed until #verifyAnticipated() is called.
* @throws junit.framework.AssertionFailedError if failFast is being changed from false to
* true and one or more unanticipated exceptions have been received.
*/
public void setFailFast(boolean failFast) throws AssertionFailedError {
if (m_failFast == false && failFast == true
&& m_unanticipated.size() > 0) {
fail("failFast is being changed from false to true and unanticipated "
+ "exceptions have been received:\n" + listUnanticipated());
}
m_failFast = failFast;
}
/**
* Returns the failFast value for this anticipator.
*
* @return failFast value. See #setFailFast(boolean) for details.
*/
public boolean isFailFast() {
return m_failFast;
}
/**
* Reset the class back to its initial state as if it had just been
* instantiated.
*/
public void reset() {
init();
}
/**
* Perform after-test verification that all anticipated java.lang.Throwable's
* have been seen and that no unanticipated java.lang.Throwable's have been
* seen.
*
* @throws junit.framework.AssertionFailedError if one or more anticipated Throwables were
* not received or one or more unanticipated Throwables were received.
*/
public void verifyAnticipated() throws AssertionFailedError {
StringBuffer error = new StringBuffer();
if (m_anticipated.size() != 0) {
error.append("Anticipated list is non-zero (has "
+ m_anticipated.size() + " entries):\n");
error.append(listAnticipated());
}
if (m_unanticipated.size() != 0) {
error.append("Unanticipated list is non-zero (has "
+ m_unanticipated.size() + " entries):\n");
error.append(listUnanticipated());
}
if (error.length() > 0) {
fail(error.toString());
}
}
private StringBuffer listAnticipated() {
return makeList(m_anticipated,
"Anticipated but unreceived Throwable: ", "\n");
}
private StringBuffer listUnanticipated() {
return makeList(m_unanticipated, "Unanticipated Throwable: ", "\n");
}
private StringBuffer makeList(List<Throwable> list, String before, String after) {
StringBuffer output = new StringBuffer();
for (Throwable t : list) {
output.append(before + t.toString() + after);
StringWriter w = new StringWriter();
PrintWriter pw = new PrintWriter(w);
t.printStackTrace(pw);
output.append(w.getBuffer());
output.append("\n");
}
return output;
}
/**
* Generate an AssertionFailedError with the specified cause.
*
* @param message error message
* @param t java.lang.Throwable that caused this error to be thrown
* @throws junit.framework.AssertionFailedError always thrown. Generated based on the
* parameters passed.
*/
public void fail(String message, Throwable t) throws AssertionFailedError {
AssertionFailedError error = new AssertionFailedError(message);
error.initCause(t);
throw error;
}
}